package controller

import (
	"gitee.com/jiebaiyou/formflow/bootstrap"
	"gitee.com/jiebaiyou/formflow/model"
	"gitee.com/jiebaiyou/formflow/pkg/bizcode"
	"gitee.com/jiebaiyou/formflow/pkg/response"
	"github.com/gin-gonic/gin"
	"golang.org/x/crypto/bcrypt"
)

// SignupController 处理用户注册相关的HTTP请求
// 它依赖于SignupService接口来实现用户注册的业务逻辑, 并使用环境配置来生成令牌
type SignupController struct {
	SignupService model.SignupService // 用户注册业务逻辑接口
	Env           *bootstrap.Config   // 环境配置, 包含令牌密钥和过期时间等信息
}

// Signup 处理新用户注册请求
func (sc *SignupController) Signup(c *gin.Context) {
	var request model.SignupRequest

	// 解析请求体并绑定到SignupRequest结构体
	err := c.ShouldBind(&request)
	if err != nil {
		// 如果请求格式不正确, 返回错误
		response.BadRequest(c, bizcode.InvalidParams.String(), err)
		return
	}

	// 检查邮箱是否已被使用
	_, err = sc.SignupService.GetUserByEmail(c, request.Email)
	if err == nil {
		// 如果邮箱已存在, 返回冲突错误
		response.BadRequest(c, bizcode.EmailAlreadyRegistered.String(), nil)
		return
	}

	// 使用bcrypt加密用户密码
	encryptedPassword, err := bcrypt.GenerateFromPassword(
		[]byte(request.Password),
		bcrypt.DefaultCost,
	)
	if err != nil {
		// 如果密码加密失败, 返回500服务器内部错误
		response.ServerError(c, bizcode.PasswordEncryptionFailed.String(), err)
		return
	}

	// 更新请求中的密码为加密后的密码
	request.Password = string(encryptedPassword)

	// 创建新的用户对象
	user := model.User{
		Name:     request.Name,
		Email:    request.Email,
		Password: request.Password,
	}

	// 将用户保存到数据库
	err = sc.SignupService.Create(c, &user)
	if err != nil {
		// 如果用户创建失败, 返回500服务器内部错误
		response.ServerError(c, bizcode.OperationFailed.String(), err)
		return
	}

	// 为新用户创建访问令牌
	accessToken, err := sc.SignupService.CreateAccessToken(&user, sc.Env.JWT.ACCESS_TOKEN_SECRET, sc.Env.JWT.ACCESS_TOKEN_EXPIRY_HOUR)
	if err != nil {
		// 如果创建令牌失败, 返回500服务器内部错误
		response.ServerError(c, bizcode.OperationFailed.String(), err)
		return
	}

	// 为新用户创建刷新令牌
	refreshToken, err := sc.SignupService.CreateRefreshToken(&user, sc.Env.JWT.REFRESH_TOKEN_SECRET, sc.Env.JWT.REFRESH_TOKEN_EXPIRY_HOUR)
	if err != nil {
		// 如果创建刷新令牌失败, 返回500服务器内部错误
		response.ServerError(c, bizcode.OperationFailed.String(), err)
		return
	}

	// 构建注册响应, 包含两个令牌
	signupResponse := model.SignupResponse{
		AccessToken:  accessToken,
		RefreshToken: refreshToken,
	}

	// 返回成功响应和令牌
	response.OK(c, bizcode.Success.String(), signupResponse)
}
